//
//  BitmapRGBA8Data.m
//  iOSUtils
//
//  Created by HJC on 11-9-16.
//  Copyright 2011年 __MyCompanyName__. All rights reserved.
//

#import "BitmapRGBA8Data.h"


extern CGContextRef NewBitmapRGBA8Context(void* bytes, size_t width, size_t height)
{
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate((void*)bytes,
                                                 width,
                                                 height,
                                                 8,
                                                 width * 4,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast);
    
    CGColorSpaceRelease(colorSpace);
    return context;
}



extern RGBAColor ColorMatrix_ProcessColor(RGBAColorMatrix* mt, RGBAColor c)
{
    int r = mt->m11 * c.red + mt->m12 * c.green + mt->m13 * c.blue + mt->m14 * c.alpha + mt->m15;
    int g = mt->m21 * c.red + mt->m22 * c.green + mt->m23 * c.blue + mt->m24 * c.alpha + mt->m25;
    int b = mt->m31 * c.red + mt->m32 * c.green + mt->m33 * c.blue + mt->m34 * c.alpha + mt->m35;
    int a = mt->m41 * c.red + mt->m42 * c.green + mt->m43 * c.blue + mt->m44 * c.alpha + mt->m45;
     
    c.red = MAX(0, MIN(r, 255));
    c.green = MAX(0, MIN(g, 255));
    c.blue = MAX(0, MIN(b, 255));
    c.alpha = MAX(0, MIN(a, 255));
    
    return c;
}



//////////////////////////////////
@implementation BitmapRGBA8Data
@synthesize width = _width;
@synthesize height = _height;
@synthesize pixels = _pixels;


- (void) dealloc
{
    free(_pixels);
    [super dealloc];
}



- (id) initWithCGImage:(CGImageRef)imageRef
{
    self = [super init];
    if (self)
    {
        _width = CGImageGetWidth(imageRef);
        _height = CGImageGetHeight(imageRef);
        NSInteger bytesLength = _width * _height * 4;
        _pixels = (unsigned int*)malloc(bytesLength);
        memset(_pixels, 0, bytesLength);
        
        CGContextRef context = NewBitmapRGBA8Context(_pixels, _width, _height);
        CGRect drawRect = CGRectMake(0, 0, _width, _height);
        CGContextDrawImage(context, drawRect, imageRef);
        CGContextRelease(context);
    }
    return self;
}


- (id)  initWithWidth:(NSInteger)width height:(NSInteger)height
{
    self = [super init];
    if (self)
    {
        _width = width;
        _height = height;
        NSInteger bytesLength = _width * _height * 4;
         _pixels = (unsigned int*)malloc(bytesLength);
        memset(_pixels, 0, bytesLength);
    }
    return self;
}


- (id) initWithBitmapData:(BitmapRGBA8Data*)data
{
    self = [super init];
    if (self)
    {
        _width = data->_width;
        _height = data->_height;
        NSInteger bytesLength = _width * _height * 4;
        _pixels = (unsigned int*)malloc(bytesLength);
        memcpy(_pixels, data->_pixels, bytesLength);
    }
    return self;
}


static void ImageDataReleaseCallback(void *info, const void *data, size_t size)
{
    free((void*)data);
}



- (UIImage*) convertToImageCopyData:(BOOL)copyData
{
    void* buffer = _pixels;
    NSInteger bufferLength = _width * _height * 4;
    CGDataProviderReleaseDataCallback releaseDataCallBack = NULL;
   
    // 需要复制多一份数据
    if (copyData)
    {
        buffer = malloc(bufferLength);
        memcpy(buffer, _pixels, bufferLength);
        releaseDataCallBack = ImageDataReleaseCallback;
    }
    
    // 设置Bitmap信息
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, releaseDataCallBack);
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * _width;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast);
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    
    // 创建Bitmap图片
    CGImageRef imageRef = CGImageCreate(_width, 
                                        _height, 
                                        bitsPerComponent, 
                                        bitsPerPixel, 
                                        bytesPerRow, 
                                        colorSpaceRef, 
                                        bitmapInfo, 
                                        provider, 
                                        NULL, 
                                        NO, 
                                        renderingIntent);
	
    UIImage* image = [UIImage imageWithCGImage:imageRef];
  
    // 清理
    CGImageRelease(imageRef);
    CGColorSpaceRelease(colorSpaceRef);
    CGDataProviderRelease(provider);
    
    return image;
}



- (void) clearWithColor:(RGBAColor)color
{
    unsigned int uint = UintFromRGBAColor(color);
    unsigned int* ptr = _pixels;
    unsigned int* endPtr = ptr + _width * _height;
    
    while (ptr != endPtr)
    {
        *ptr = uint;
        ptr++;
    }
}



- (RGBAColor) colorAtPosX:(NSInteger)x posY:(NSInteger)y
{
    if (x < 0 || x >= _width || y < 0 || y >= _height)
    {
        return RGBAColorMake(0, 0, 0, 0);
    }
    
    return RGBAColorFromUint(_pixels[_width * y + x]);
}


- (void) processWithColorMatrix:(RGBAColorMatrix*)colorMatrix
{
    unsigned int* ptr = _pixels;
    unsigned int* endPtr = ptr + _width * _height;
    RGBAColorUnion u;
    while (ptr != endPtr)
    {
        u.uint = *ptr;
        u.color = ColorMatrix_ProcessColor(colorMatrix, u.color);
        *ptr = u.uint;
        ptr++;
    }
}



- (void) processWithCallBack:(ColorProcessCallBack)callBack context:(void*)context
{
    unsigned int* ptr = _pixels;
    unsigned int* endPtr = ptr + _width * _height;
    RGBAColorUnion u;
    while (ptr != endPtr)
    {
        u.uint = *ptr;
        u.color = callBack(context, u.color);
        *ptr = u.uint;
        ptr++;
    }
}


@end
